﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DbFrame.Ado
{
    using System.Data;
    using Dapper;
    using DbFrame.Class;

    /// <summary>
    /// 数据操作 帮助类 兼容类
    /// </summary>
    public class DbHelper
    {
        private string _ConnectionString { get; set; }
        private DataBaseType _DataBaseType { get; set; }

        public DbHelper(string ConnectionString, DataBaseType DataBaseType)
        {
            this._ConnectionString = ConnectionString;
            this._DataBaseType = DataBaseType;
        }

        /// <summary>
        /// 获取连接对象
        /// </summary>
        /// <returns></returns>
        public IDbConnection GetDbConnection()
        {
            if (this._DataBaseType == DataBaseType.SqlServer)
            {
                return new MsSqlDatabase(this._ConnectionString).GetDbConnection();
            }
            else if (this._DataBaseType == DataBaseType.MySql)
            {
                return new MySqlDatabase(this._ConnectionString).GetDbConnection();
            }
            else if (this._DataBaseType == DataBaseType.Oracle)
            {
                return new OracleDatabase(this._ConnectionString).GetDbConnection();
            }

            throw new Exception("暂不支持 数据类型");
        }

        /// <summary>
        /// 执行 Insert Delete Update
        /// </summary>
        /// <param name="SqlStr"></param>
        /// <param name="Param"></param>
        /// <returns></returns>
        public bool Execute(string SqlStr, object Param)
        {
            var rows = this.GetDbConnection().Execute(SqlStr, Param);
            return rows > 0;
        }

        /// <summary>
        /// 执行 Insert Delete Update 并且 返回 值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="SqlStr"></param>
        /// <param name="Param"></param>
        /// <returns></returns>
        public T ExecuteScalar<T>(string SqlStr, object Param)
        {
            return this.GetDbConnection().ExecuteScalar<T>(SqlStr, Param);
        }

        /// <summary>
        /// 查询单行单列数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="SqlStr"></param>
        /// <param name="Param"></param>
        /// <returns></returns>
        public T QuerySingleOrDefault<T>(string SqlStr, object Param)
        {
            return this.GetDbConnection().QuerySingleOrDefault<T>(SqlStr, Param);
        }

        /// <summary>
        /// 查询单行 数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T QueryFirstOrDefault<T>(string SqlStr, object Param)
        {
            return this.GetDbConnection().QueryFirstOrDefault<T>(SqlStr, Param);
        }

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="SqlStr"></param>
        /// <param name="Param"></param>
        /// <returns></returns>
        public IEnumerable<T> Query<T>(string SqlStr, object Param)
        {
            if (typeof(T).Name == new Dictionary<string, object>().GetType().Name)
            {
                return (IEnumerable<T>)Mapping.TableToList(this.Query(SqlStr, Param));
            }
            else
            {
                if (Param == null)
                    return this.GetDbConnection().Query<T>(SqlStr);
                return this.GetDbConnection().Query<T>(SqlStr, Param);
            }
        }

        /// <summary>
        /// 执行查询 得到 DataTable
        /// </summary>
        /// <param name="SqlStr"></param>
        /// <param name="Param"></param>
        /// <returns></returns>
        public DataTable Query(string SqlStr, object Param)
        {
            IDataReader _IDataReader = null;
            if (Param == null)
                _IDataReader = this.GetDbConnection().ExecuteReader(SqlStr);
            else
                _IDataReader = this.GetDbConnection().ExecuteReader(SqlStr, Param);
            return Mapping.IDataReaderToDataTable(_IDataReader);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="SqlStr"></param>
        /// <param name="Page"></param>
        /// <param name="PageSize"></param>
        /// <param name="Total"></param>
        /// <returns></returns>
        public DataTable FindPaging(string SqlStr, int Page, int PageSize, out int Total, object Param)
        {
            if (this._DataBaseType == DataBaseType.SqlServer)
            {
                return new MsSqlDatabase(this._ConnectionString).FindPaging(SqlStr, Page, PageSize, out Total, Param);
            }
            else if (this._DataBaseType == DataBaseType.MySql)
            {
                return new MySqlDatabase(this._ConnectionString).FindPaging(SqlStr, Page, PageSize, out Total, Param);
            }
            else if (this._DataBaseType == DataBaseType.Oracle)
            {
                return new OracleDatabase(this._ConnectionString).FindPaging(SqlStr, Page, PageSize, out Total, Param);
            }
            Total = 0;
            return null;
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <param name="li"></param>
        /// <param name="_CallBack"></param>
        /// <returns></returns>
        public bool Commit(List<SQL> li, Action<int, Class.SQL, IDbTransaction> _CallBack = null)
        {
            var conn = this.GetDbConnection();
            conn.Open();
            using (var _BeginTransaction = conn.BeginTransaction())
            {
                try
                {
                    for (int i = 0; i < li.Count; i++)
                    {
                        var _SQL = li[i];
                        if (_CallBack != null) _CallBack(i, _SQL, _BeginTransaction);
                        conn.Execute(_SQL.Sql_Parameter, _SQL.Parameter, _BeginTransaction);
                    }
                    _BeginTransaction.Commit();
                    return true;
                }
                catch (Exception ex)
                {
                    _BeginTransaction.Rollback();
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }
            }
        }









    }
}
